home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / dev / sun4.md / devTMR.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  9KB  |  333 lines

  1. /* 
  2.  * devTMR.c --
  3.  *
  4.  *    The devTMR is a mirosecond resolution timer installable in the
  5.  *    DES chip sockets on some sun3 and sun4 computers. It uses
  6.  *    the AMD Am9513 timer chip. It is used to provide high resolution
  7.  *    timings for the Sprite kernel and user programs.  
  8.  *
  9.  * Copyright 1989 Regents of the University of California
  10.  * Permission to use, copy, modify, and distribute this
  11.  * software and its documentation for any purpose and without
  12.  * fee is hereby granted, provided that the above copyright
  13.  * notice appear in all copies.  The University of California
  14.  * makes no representations about the suitability of this
  15.  * software for any purpose.  It is provided "as is" without
  16.  * express or implied warranty.
  17.  */
  18.  
  19. #ifndef lint
  20. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/dev/sun4.md/devTMR.c,v 9.2 90/09/11 12:41:06 rab Exp $ SPRITE (Berkeley)";
  21. #endif /* not lint */
  22.  
  23. #include "sprite.h"
  24. #include "mach.h"
  25. #include "devInt.h"
  26. #include "vm.h"
  27. #include "vmMach.h"
  28. #include "devTMR.h"
  29.  
  30. volatile DevTimerChip *dev_TimerAddr;
  31. int devTimerJunkVar;
  32.  
  33. static void TimerInit _ARGS_((register volatile DevTimerChip *tmrp));
  34.  
  35.  
  36. /*
  37.  *----------------------------------------------------------------------
  38.  *
  39.  * Dev_TimerProbe --
  40.  *
  41.  *    Check for the existant of the timer chip controller. 
  42.  *
  43.  * Results:
  44.  *    DEV_NO_CONTROLLER if chip not present, the address of the 
  45.  *    chip otherwise.
  46.  *
  47.  * Side effects:
  48.  *    dev_TimerAddr is initialized to the address of the time if it 
  49.  *    is present and the timer is started running in one microsecond
  50.  *    mode.
  51.  *
  52.  *----------------------------------------------------------------------
  53.  */
  54. ClientData
  55. Dev_TimerProbe(ctrlLocPtr)
  56.      DevConfigController    *ctrlLocPtr;    /* Controller location. */
  57. {
  58.     register volatile DevTimerChip *tmrbase = 
  59.     (DevTimerChip *) ctrlLocPtr->address;
  60.     ReturnStatus status;
  61.     char    byte;
  62.  
  63.     byte = DEV_TIMER_RESET;
  64.     status = Mach_Probe(1,&byte, (char *)&(tmrbase->cmdPort));
  65.     if (status != SUCCESS) {
  66.     return DEV_NO_CONTROLLER;
  67.     }
  68.  
  69.     MACH_DELAY(4); 
  70.     status = Mach_Probe(1,(char *)&(tmrbase->d_reg), &byte);
  71.     if ((status != SUCCESS) || (byte == (char)0xff)) {
  72.     return DEV_NO_CONTROLLER;
  73.     }
  74.     dev_TimerAddr = tmrbase;
  75.     return ((ClientData) dev_TimerAddr);
  76. }
  77.  
  78.  
  79. /*
  80.  * Initialize device.  
  81.  */
  82. static struct TimerSetup {
  83.    unsigned char model;
  84.    unsigned char modeh;
  85.    unsigned char loadl;
  86.    unsigned char loadh;
  87.    unsigned char holdl;
  88.    unsigned char holdh;
  89.    } TimerSetup[] = { {DEV_TIMER_CNT, DEV_TIMER_F2, 0,0,0,0},
  90.                   {DEV_TIMER_CNT, DEV_TIMER_TC, 0,0,0,0},
  91.                   {DEV_TIMER_CNT, DEV_TIMER_TC, 0,0,0,0},
  92.                   {DEV_TIMER_CNT, DEV_TIMER_TC, 0,0,0,0},
  93.                   {DEV_TIMER_CNT, DEV_TIMER_TC, 0,0,0,0} };
  94.  
  95.  
  96. /*
  97.  *----------------------------------------------------------------------
  98.  *
  99.  * TimerInit --
  100.  *
  101.  * The Am9513 counter's 5 stages is concatenated to form an 80 bit
  102.  * counter.   
  103.  *
  104.  * Results:
  105.  *    None
  106.  *
  107.  * Side effects:
  108.  *
  109.  *----------------------------------------------------------------------
  110.  */
  111. static void
  112. TimerInit(tmrp)
  113.     register volatile DevTimerChip *tmrp;
  114. {
  115.     int i;  /* cntr pointer */
  116.  
  117.     DISABLE_INTR();
  118.     DEV_TIMER_CMD_PORT;
  119.     tmrp->d_reg = DEV_TIMER_RESET; 
  120.     MACH_DELAY(2);
  121.     tmrp->d_reg = DEV_TIMER_LDALL; 
  122.     MACH_DELAY(2);
  123.     tmrp->d_reg = DEV_TIMER_LDDPTR|DEV_TIMER_ELEMCYC; 
  124.     MACH_DELAY(2);
  125.     DEV_TIMER_DATA_PORT;
  126.     for (i = 0; i < 5; ++i) {
  127.        tmrp->d_reg = TimerSetup[i].model; MACH_DELAY(2);
  128.        tmrp->d_reg = TimerSetup[i].modeh; MACH_DELAY(2);
  129.        tmrp->d_reg = TimerSetup[i].loadl; MACH_DELAY(2);
  130.        tmrp->d_reg = TimerSetup[i].loadh; MACH_DELAY(2);
  131.        tmrp->d_reg = TimerSetup[i].holdl; MACH_DELAY(2);
  132.        tmrp->d_reg = TimerSetup[i].holdh; MACH_DELAY(2);
  133.     }
  134.     DEV_TIMER_CMD_PORT;
  135.     tmrp->d_reg = DEV_TIMER_ARM;
  136.     ENABLE_INTR();
  137. }
  138.  
  139. /*
  140.  *----------------------------------------------------------------------
  141.  *
  142.  * Dev_TimerIOControl --
  143.  *
  144.  *    Perform device-specific functions with the timer chip.
  145.  *
  146.  * Results:
  147.  *    SUCCESS        -
  148.  *
  149.  * Side effects:
  150.  *    Variable.
  151.  *
  152.  *----------------------------------------------------------------------
  153.  */
  154. /*ARGSUSED*/
  155. ReturnStatus
  156. Dev_TimerIOControl(devicePtr, ioctlPtr, replyPtr)
  157.     Fs_Device            *devicePtr;
  158.     Fs_IOCParam        *ioctlPtr;
  159.     Fs_IOReply        *replyPtr;
  160. {
  161.    register volatile DevTimerChip *tmrp = dev_TimerAddr;
  162.    register DevTimerVal *set;
  163.    unsigned int t0, t1;
  164.    DevTimerTest *tare;
  165.  
  166.     replyPtr->length = ioctlPtr->outBufSize;
  167.     switch (ioctlPtr->command) {
  168.        case IOC_DEV_TIMER_INIT: 
  169.             TimerInit(tmrp); 
  170.             return (SUCCESS);
  171.        case IOC_DEV_TIMER_CMDWR:   
  172.             if ( ioctlPtr->inBufSize != 1) {
  173.             return(GEN_INVALID_ARG);
  174.             } 
  175.             DEV_TIMER_CMD_PORT;
  176.             tmrp->d_reg = *(unsigned char *) ioctlPtr->inBuffer;
  177.             return(SUCCESS); 
  178.        case IOC_DEV_TIMER_DATAWR:  
  179.             if ( ioctlPtr->inBufSize != 1) {
  180.             return(GEN_INVALID_ARG);
  181.             } 
  182.             DEV_TIMER_DATA_PORT;
  183.             tmrp->d_reg = *(unsigned char *) ioctlPtr->inBuffer;
  184.             return(SUCCESS); 
  185.       case IOC_DEV_TIMER_CMDRD:   
  186.             if ( ioctlPtr->outBufSize != 1) {
  187.             return(GEN_INVALID_ARG);
  188.             } 
  189.             DEV_TIMER_CMD_PORT;
  190.             *( unsigned char *) ioctlPtr->outBuffer = tmrp->d_reg;
  191.             return(SUCCESS);
  192.        case IOC_DEV_TIMER_DATARD:  
  193.             if ( ioctlPtr->outBufSize != 1) {
  194.             return(GEN_INVALID_ARG);
  195.             } 
  196.             DEV_TIMER_DATA_PORT;
  197.             *( unsigned char *) ioctlPtr->outBuffer = tmrp->d_reg;
  198.             return(SUCCESS);
  199.        case IOC_DEV_TIMER_TEST:
  200.             if (ioctlPtr->outBufSize != sizeof(DevTimerTest)) {
  201.             return(GEN_INVALID_ARG);
  202.             } 
  203.             tare = (DevTimerTest *) ioctlPtr->outBuffer;
  204.             Dev_TimerReadReg( (unsigned char *) &t0, 4); 
  205.             Dev_TimerReadReg( (unsigned char *) &t1, 4);
  206.             tare->proc = t1-t0;
  207.             Dev_TimerReadRegInline(&t0); Dev_TimerReadRegInline(&t1);
  208.             tare->inLine = t1-t0;
  209.             return(SUCCESS);
  210.        case IOC_DEV_TIMER_SET:
  211.             if (ioctlPtr->inBufSize != sizeof(DevTimerVal)) {
  212.             return(GEN_INVALID_ARG);
  213.             } 
  214.             DEV_TIMER_CMD_PORT;
  215.             set = (DevTimerVal *) ioctlPtr->inBuffer;
  216.             DISABLE_INTR();
  217.             tmrp->d_reg = set->cmd; 
  218.             MACH_DELAY(2);
  219.             DEV_TIMER_DATA_PORT;
  220.             tmrp->d_reg = set->datalo;
  221.             MACH_DELAY(2);
  222.             tmrp->d_reg = set->datahi;
  223.             ENABLE_INTR();
  224.             return(SUCCESS);
  225.        default :  
  226.        return (GEN_INVALID_ARG);
  227.     }
  228. }
  229.  
  230. /*
  231.  *----------------------------------------------------------------------
  232.  *
  233.  * Dev_TimerRead --
  234.  *
  235.  *    Read data from the Timer registers.  
  236.  *
  237.  * Results:
  238.  *    SUCCESS        - the data was obtained.
  239.  *    FAILURE        - an invalid argument.
  240.  *
  241.  * Side effects:
  242.  *    None.
  243.  *
  244.  *----------------------------------------------------------------------
  245.  */
  246. /*ARGSUSED*/
  247. ReturnStatus
  248. Dev_TimerRead(devicePtr, readPtr, replyPtr)
  249.     Fs_Device    *devicePtr;
  250.     Fs_IOParam    *readPtr;    /* Read parameter block */
  251.     Fs_IOReply    *replyPtr;    /* Return length and signal */ 
  252. {
  253.  
  254.    int        bufSize;    /* Size of buffer. */
  255.  
  256.    bufSize = readPtr->length;
  257.    if (bufSize > 10) {
  258.        bufSize  = 10;
  259.    }
  260.    Dev_TimerReadReg( (unsigned char *) readPtr->buffer, bufSize);
  261.    replyPtr->length = bufSize;
  262.  
  263.    return (SUCCESS);
  264. }
  265.  
  266. /*
  267.  *----------------------------------------------------------------------
  268.  *
  269.  * Dev_TimerReadReg --
  270.  *
  271.  *    Read a value from the timer's regiser
  272.  *
  273.  * Results:
  274.  *    None.
  275.  *
  276.  * Side effects:
  277.  *    None.
  278.  *
  279.  *----------------------------------------------------------------------
  280.  */
  281.  
  282.  
  283. void
  284. Dev_TimerReadReg( cntrs, cnt)
  285.   register unsigned char *cntrs;
  286.   register int cnt;
  287. {
  288.    register volatile DevTimerChip *tmrp = dev_TimerAddr;
  289.  
  290.    DISABLE_INTR();
  291.    DEV_TIMER_CMD_PORT;
  292.    tmrp->d_reg = DEV_TIMER_SAVE; MACH_DELAY(1);
  293.    tmrp->d_reg = DEV_TIMER_LDDPTR|DEV_TIMER_HOLDCYC;
  294.    DEV_TIMER_DATA_PORT;
  295.    for (; cnt > 0; cnt--) {
  296.       MACH_DELAY(1);
  297.       cntrs[cnt] = tmrp->d_reg;
  298.    }
  299.    ENABLE_INTR();
  300. }
  301.  
  302. /*
  303.  *----------------------------------------------------------------------
  304.  *
  305.  * Dev_TimerOpen --
  306.  *
  307.  *    Open the /dev/timer device.  
  308.  *
  309.  * Results:
  310.  *    SUCCESS        - the device was opened.
  311.  *
  312.  * Side effects:
  313.  *    The cc is "opened" and static variables are initialized.
  314.  *
  315.  *----------------------------------------------------------------------
  316.  */
  317.  
  318.  
  319. /*ARGSUSED*/
  320. ReturnStatus
  321. Dev_TimerOpen(devicePtr, useFlags, notifyToken, flagsPtr)
  322.     Fs_Device *devicePtr;    /* Specifies type and unit number. */
  323.     int useFlags;        /* Flags from the stream being opened */
  324.     Fs_NotifyToken notifyToken;    /* Used for Fs call-back to notify waiting
  325.                  * processes that the console device is ready.*/
  326.     int *flagsPtr;              /* OUT: Device IO flags */
  327. {
  328.     if (dev_TimerAddr == (volatile DevTimerChip *) 0) {
  329.     return DEV_NO_DEVICE;
  330.     }
  331.     return SUCCESS;
  332. }
  333.